/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "utf16reader.h"

namespace ime_pinyin
{

#define MIN_BUF_LEN 128
#define MAX_BUF_LEN 65535

	Utf16Reader::Utf16Reader()
	{
		fp_ = NULL;
		buffer_ = NULL;
		buffer_total_len_ = 0;
		buffer_next_pos_ = 0;
		buffer_valid_len_ = 0;
	}

	Utf16Reader::~Utf16Reader()
	{
		if (NULL != fp_) {
			fclose(fp_);
		}

		if (NULL != buffer_) {
			delete [] buffer_;
		}
	}


	bool Utf16Reader::open(const char *filename, size_t buffer_len)
	{
		if (filename == NULL) {
			return false;
		}

		if (buffer_len < MIN_BUF_LEN) {
			buffer_len = MIN_BUF_LEN;
		} else if (buffer_len > MAX_BUF_LEN) {
			buffer_len = MAX_BUF_LEN;
		}

		buffer_total_len_ = buffer_len;

		if (NULL != buffer_) {
			delete [] buffer_;
		}
		buffer_ = new char16[buffer_total_len_];
		if (NULL == buffer_) {
			return false;
		}

		if ((fp_ = fopen(filename, "rb")) == NULL) {
			return false;
		}

		// the UTF16 file header, skip
		char16 header;
		if (fread(&header, sizeof(header), 1, fp_) != 1 || header != 0xfeff) {
			fclose(fp_);
			fp_ = NULL;
			return false;
		}

		return true;
	}

	char16 *Utf16Reader::readline(char16 *read_buf, size_t max_len)
	{
		if (NULL == fp_ || NULL == read_buf || 0 == max_len) {
			return NULL;
		}

		size_t ret_len = 0;

		do {
			if (buffer_valid_len_ == 0) {
				buffer_next_pos_ = 0;
				buffer_valid_len_ = fread(buffer_, sizeof(char16),
				                          buffer_total_len_, fp_);
				if (buffer_valid_len_ == 0) {
					if (0 == ret_len) {
						return NULL;
					}
					read_buf[ret_len] = (char16)'\0';
					return read_buf;
				}
			}

			for (size_t i = 0; i < buffer_valid_len_; i++) {
				if (i == max_len - 1 ||
				        buffer_[buffer_next_pos_ + i] == (char16)'\n') {
					if (ret_len + i > 0 && read_buf[ret_len + i - 1] == (char16)'\r') {
						read_buf[ret_len + i - 1] = (char16)'\0';
					} else {
						read_buf[ret_len + i] = (char16)'\0';
					}

					i++;
					buffer_next_pos_ += i;
					buffer_valid_len_ -= i;
					if (buffer_next_pos_ == buffer_total_len_) {
						buffer_next_pos_ = 0;
						buffer_valid_len_ = 0;
					}
					return read_buf;
				} else {
					read_buf[ret_len + i] = buffer_[buffer_next_pos_ + i];
				}
			}

			ret_len += buffer_valid_len_;
			buffer_valid_len_ = 0;
		} while (true);

		// Never reach here
		return NULL;
	}

	bool Utf16Reader::close()
	{
		if (NULL != fp_) {
			fclose(fp_);
		}
		fp_ = NULL;

		if (NULL != buffer_) {
			delete [] buffer_;
		}
		buffer_ = NULL;
		return true;
	}
}  // namespace ime_pinyin
